package dsx.config;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class Config {
	private static String configFile = "config.xml";
	private static String configDir = "conf/";
	private static ArrayList<String> configList = null;
	private static HashMap<String, Integer> lockMap = new HashMap<String, Integer>();
	private static boolean locked = false;
	private static Object lock = new Object();

	private static void lockConfig() {
		while (true) {
			synchronized (lock) {
				if (!locked) {
					locked = true;
					return;
				}
			}
			try {
				Thread.sleep(20);
			} catch (Exception ex) {
			}
		}
	}

	private static void releaseConfig() {
		synchronized (lock) {
			locked = false;
		}
	}

	public static void lockConfig(String configName) {
		while (true) {
			synchronized (lock) {
				if (lockMap.containsKey(configName)) {
					if (lockMap.get(configName).equals(0)) {
						lockMap.put(configName, 1);
						return;
					}
				} else {
					lockMap.put(configName, 1);
					return;
				}
			}
			try {
				Thread.sleep(20);
			} catch (Exception ex) {
			}
		}
	}

	public static void releaseConfig(String configName) {
		synchronized (lock) {
			if (lockMap.containsKey(configName)) {
				lockMap.put(configName, 0);
			}
		}
	}

	public static String get(String sectionName, String fieldName)
			throws Exception {
		lockConfig();
		try {
			ArrayList<String> confLst = getConfigFileList();
			if (confLst != null) {
				for (int h = 0; h < confLst.size(); h++) {
					NodeList sections = getNodeList(confLst.get(h), sectionName);
					for (int i = 0; i < sections.getLength(); i++) {
						NodeList fields = ((Element) sections.item(i))
								.getElementsByTagName(fieldName);
						if (fields != null && fields.getLength() > 0)
							return fields.item(0).getTextContent();
					}
				}
			}
			throw new Exception("Node not exist.");
		} catch (Exception ex) {
			return null;
		} finally {
			releaseConfig();
		}
	}

	public static ArrayList<String> getFields(String sectionName,
			String fieldName) throws Exception {
		lockConfig();
		try {
			ArrayList<String> ret = new ArrayList<String>();
			ArrayList<String> confLst = getConfigFileList();
			if (confLst != null) {
				for (int h = 0; h < confLst.size(); h++) {
					NodeList sections = getNodeList(confLst.get(h), sectionName);
					for (int i = 0; i < sections.getLength(); i++) {
						NodeList fields = ((Element) sections.item(i))
								.getElementsByTagName(fieldName);
						if (fields != null && fields.getLength() > 0) {
							for (int j = 0; j < fields.getLength(); j++)
								ret.add(fields.item(j).getTextContent());
						}
					}
				}
			}
			return ret;
		} catch (Exception ex) {
			return null;
		} finally {
			releaseConfig();
		}
	}

	public static String[] get(String sectionName, String[] fieldName) {
		lockConfig();
		try {
			String[] fieldValue = new String[fieldName.length];
			for (int i = 0; i < fieldName.length; i++)
				fieldValue[i] = "";
			ArrayList<String> confLst = getConfigFileList();
			if (confLst != null) {
				for (int h = 0; h < confLst.size(); h++) {
					NodeList sections = getNodeList(confLst.get(h), sectionName);
					if (sections != null && sections.getLength() > 0) {
						for (int i = 0; i < sections.getLength(); i++) {
							for (int j = 0; j < fieldName.length; j++) {
								if (fieldValue[j] == "") {
									NodeList fields = ((Element) sections
											.item(i))
											.getElementsByTagName(fieldName[j]);
									if (fields != null
											&& fields.getLength() > 0)
										fieldValue[j] = fields.item(0)
												.getTextContent();
								}
							}
						}
						return fieldValue;
					}
				}
			}
			return null;
		} catch (Exception ex) {
			return null;
		} finally {
			releaseConfig();
		}
	}

	public static ArrayList<ConfigItem> get(String sectionName) {
		lockConfig();
		try {
			ArrayList<String> confLst = getConfigFileList();
			if (confLst != null) {
				for (int h = 0; h < confLst.size(); h++) {
					NodeList sections = getNodeList(confLst.get(h), sectionName);
					if (sections != null && sections.getLength() > 0) {
						for (int i = 0; i < sections.getLength(); i++) {
							NodeList fields = sections.item(i).getChildNodes();
							if (fields != null && fields.getLength() > 0) {
								ArrayList<ConfigItem> itemList = new ArrayList<ConfigItem>();
								for (int j = 0; j < fields.getLength(); j++) {
									String nodeName = fields.item(j)
											.getNodeName();
									if (nodeName == null
											|| nodeName.trim().isEmpty()
											|| nodeName.equals("#text"))
										continue;
									ConfigItem configItem = new ConfigItem();
									configItem.name = nodeName;
									configItem.value = fields.item(j)
											.getTextContent();
									itemList.add(configItem);
								}
								return itemList;
							}
						}
						
					}
				}
			}
			return null;
		} catch (Exception ex) {
			return null;
		} finally {
			releaseConfig();
		}
	}

	public static ArrayList<ArrayList<ConfigItem>> getSections(
			String sectionName) {
		ArrayList<ArrayList<ConfigItem>> sectionList = new ArrayList<ArrayList<ConfigItem>>();
		lockConfig();
		try {
			ArrayList<String> confLst = getConfigFileList();
			if (confLst != null) {
				for (int h = 0; h < confLst.size(); h++) {
					NodeList sections = getNodeList(confLst.get(h), sectionName);
					if (sections != null && sections.getLength() > 0) {
						for (int i = 0; i < sections.getLength(); i++) {
							NodeList fields = sections.item(i).getChildNodes();
							if (fields != null && fields.getLength() > 0) {
								ArrayList<ConfigItem> itemList = new ArrayList<ConfigItem>();
								for (int j = 0; j < fields.getLength(); j++) {
									String nodeName = fields.item(j)
											.getNodeName();
									if (nodeName == null
											|| nodeName.trim().isEmpty()
											|| nodeName.equals("#text"))
										continue;
									ConfigItem configItem = new ConfigItem();
									configItem.name = nodeName;
									configItem.value = fields.item(j)
											.getTextContent();
									itemList.add(configItem);
								}
								sectionList.add(itemList);
							}
						}
					}
				}
			}
			return sectionList;
		} catch (Exception ex) {
			return null;
		} finally {
			releaseConfig();
		}
	}

	private static NodeList getNodeList(String filePath, String tagName)
			throws Exception {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document document = db.parse(new File(filePath));
		Element root = document.getDocumentElement();
		return root.getElementsByTagName(tagName);
	}

	public static String getNodeValue(Element elem, String nodeName) {
		NodeList nl = elem.getElementsByTagName(nodeName);
		if (nl.getLength() > 0)
			return nl.item(0).getTextContent();
		else
			return "";
	}

	private static ArrayList<String> getConfigFileList() throws Exception {
		if (configList == null) {
			configList = new ArrayList<String>();
			File file = new File(configFile);
			if (file.exists())
				configList.add(configFile);
			getFileList(configDir, configList);
		}
		return configList;
	}

	private static void getFileList(String strPath, ArrayList<String> fileList)
			throws Exception {
		File dir = new File(strPath);
		File[] files = dir.listFiles(); // 该文件目录下文件全部放入数组
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				String fileName = files[i].getName();
				if (files[i].isDirectory()) { // 判断是文件还是文件夹
					getFileList(files[i].getAbsolutePath(), fileList); // 获取文件绝对路径
				} else if (fileName.endsWith("xml")) { // 判断文件名是否以.xml结尾
					fileList.add(files[i].getAbsolutePath());
				} else {
					continue;
				}
			}
		}
	}

}
